
(function (window) {
  // http://frontlog.9tech.cn/js/changeyouErrorHandle.js // 测试环境的线上地址
  // 将捕获错误信息函数定义为全局的不可重写的唯一方法
  Object.defineProperty(window, 'changeyouErrorHandle', {
    get() {
      return handleErrorMessage
    },
    set(newVal) {
      console.error('TypeError: Cannot redefine property : window.handleError is existed !!!')
      return
    }
  })
  // 三种错误类型 运行时同步错误 资源加载错误 异步错误
  const ERROR_RUNTIME = 'ERROR_RUNTIME'
  const ERROR_RESOURCE = 'ERROR_RESOURCE'
  const ERROR_ASYNC = 'ERROR_ASYNC'
  // http://frontlog.9tech.cn/log?from=visitor.cloudgs.9tech.cn
  const requestErrorURL = `http://frontlog.9tech.cn/log?from=${getWebHOST()}` // 测试环境接口
  let webVersion = null
  // 获取项目版本号
  function getWebVersion() {
    if (webVersion != null) return webVersion
    try {
      const version_meta = document.querySelector('meta[http-equiv="version"]')
      version_meta && (webVersion = version_meta.content)
      return webVersion
    } catch (error) {
      console.error(error)
    }
  }
  // 获取页面当前url
  function getWebURL() {
    return window.location.href
  }
  // 获取页面当前host
  function getWebHOST() {
    return window.location.host
  }
  // 监听全局同步错误和资源加载错误
  window.addEventListener('error', function (e) {
    let errorData = {}
    errorData.url = getWebURL()
    errorData.version = getWebVersion()
    errorData.from = getWebHOST()
    if (e.target === window) {
      errorData.type = ERROR_RUNTIME
      errorData.message = e.message
      errorData.lineno = e.lineno
      errorData.colno = e.colno
      errorData.stack = e.error.stack
    } else {
      var tgt = e.target
      const srcText = tgt.attributes.href ? tgt.attributes.href.value : tgt.attributes.src.value
      errorData.type = ERROR_RESOURCE
      errorData.message = 'load resource error !!!'
      errorData.outerHTML = encodeURI(tgt.outerHTML)
      errorData.src = tgt.src || tgt.href
      errorData.srcText = srcText
    }
    changeyouErrorHandle(errorData)
  }, true)
  // 监听全局的异步错误
  window.addEventListener('unhandledrejection', function (e) {
    let errorData = {}
    errorData.url = getWebURL()
    errorData.version = getWebVersion()
    errorData.from = getWebHOST()
    errorData.type = ERROR_ASYNC
    errorData.message = e.reason.message
    errorData.stack = e.reason.stack
    changeyouErrorHandle(errorData)
  }, true)
  // 处理错误消息
  function handleErrorMessage(err, logErr) {
    sendErrorByAjax(err)
    if (logErr) {
      console.error(err)
    }
  }
  // 发送错误消息
  function sendErrorByAjax(errData) {
    try {
      let xhr = XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP')
      xhr.onreadystatechange = function () {
        if (xhr.readyState == 4) {
          if (xhr.status >= 200 && xhr.status < 300) {
            // console.log(xhr.responseText)
          } else {
            // console.log('================================================xhr.status !== 200')
          }
        } else {
          // console.log('================================================xhr.readyState !== 4') 
        }
      }
      xhr.open('post', requestErrorURL, true)
      // xhr.timeout = 500
      // xhr.ontimeout=function(){
      //   console.log('ajax is timeout !!!')
      // }
      xhr.setRequestHeader('Content-Type', 'application/json;charset=UTF-8')
      xhr.send(JSON.stringify(errData))
    } catch (error) {
      console.error(error)
    }
  }
})(window)